#include<iostream>
#include<string>
#include<opencv2/opencv.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/core/core.hpp>
#include<boost/thread.hpp>
#include<boost/circular_buffer.hpp>
#include<boost/algorithm/string.hpp>
#include<future>
#include<mutex>
#include<thread>
#include<condition_variable>
#include<fstream>
#include"json.hpp"
#include<boost/format.hpp>
using namespace nlohmann;
//using namespace boost;

using json = nlohmann::json;
using namespace std;
using namespace cv;
void hello()
{
	for (int i = 0; i < 10; i++) {
		cout << "hello" << endl;
		boost::this_thread::sleep_for(boost::chrono::duration<double, boost::milli>(20));
	}
}
void world()
{
	for (int i = 0; i < 10; i++) {
		cout << "world" << endl;
		boost::this_thread::sleep_for(boost::chrono::duration<double, boost::milli>(40));
	}
}
void CVshow()
{
	string imgPath = "img.jpg";
	Mat img;
	img = imread(imgPath);
	resize(img, img, Size(1280, 720));
	cout << "hello world" << endl;
	imshow("luffy", img);
	waitKey(0);
}
int main_1()
{
	boost::thread t_hello(hello);
	boost::thread t_world(world);

	t_hello.join();
	t_world.join();
	return 0;
}

void fun1(promise<bool>& str)
{
	str.set_value(true);
}

int main_3()
{
	promise<bool> promiseObj;
	future<bool> futObj = promiseObj.get_future();
	thread t1(fun1, ref(promiseObj));
	t1.detach();
	while (true) {
		cout << futObj.get() << endl;
		cout << "future success" << endl;
	}
	return 0;
}

void ini_test()
{
	ifstream file(".\\test.json");
	json j = json::parse(file);
	cout << j.dump(4) << endl;
	for (auto it = j.begin(); it != j.end(); it++) {
		if (it->is_null()) {
			cerr << it.key() << " is null" << endl;
			continue;


		}
		cout << it.value() << endl;
	}
}

class Recognize {

protected:

	// data
	int i;
	string str;
	static int num;

public:

	// constructor
	Recognize(int _i, string _str) :i(_i), str(_str) { cout << "constructor Recognize" << endl; }
	Recognize() { init(); }

public:

	// member function
	void print()
	{
		cout << "Recognize print ..." << endl;
		cout << str << " " << i << "\t num:" << num << endl;
	}

	void init()
	{
		cout << "Recognize init ..." << endl;
		i = 1;
		str = "null";
	}

	void setnum(int n)
	{
		num = n;
	}
};


class Exist : public Recognize {

protected:

	// data
	string e_str;

public:

	//constructor
	Exist(int _i, string _str, string _e_str) : Recognize(_i, _str), e_str(_e_str) {}

	Exist() {
		init();
	}


public:

	// member function
	void init()
	{
		cout << "Exist init ..." << endl;
		e_str = "e_null";
		i = 0;
		str = "null";
	}

	void print()
	{
		cout << "Exist print ..." << endl;
		//Recognize::print();
		cout << e_str << " " << i << " " << str << "\t num:" << num << endl;

	}

	void format()
	{
		char buffer[100];

		snprintf(buffer, 100, "%s, %d", this->e_str.c_str(), this->i);
		this->str.assign(buffer);
	}

	void boostformat()
	{
		double d = 3.1415926;
		boost::format fmt("%1$-8.3f, %2%");
		fmt% d;
		fmt% e_str;
		cout << fmt.str() << endl;
	}

	int getnum()
	{
		return num;
	}
};



int Recognize::num(0);



class MyClass
{
private:
	string id;


protected:
	int var = 1;
	//string id;
	static map<string, MyClass*> map_id_var;

public:
	MyClass(string _id) : id(_id) { init(); }
	MyClass();

public:
	void set_id(int newid)
	{
		id = newid;
	}

	void print()
	{
		cout << boost::format("id: %1$-8svar: %2$-8d\n") % id % var;
	}

	virtual void stop()
	{
		cout << "call MyClass::stop()\n";
		this->var = 0;
	}

	string getid()
	{
		return id;
	}

	void init()
	{
		cout << "call MyClass::init()" << endl;
	}


	
};


class SonClass : public MyClass
{

private:
	string id;

public:
	SonClass(string id) : MyClass(id) {}

public:
	
	virtual void stop()
	{
		cout << "call SonClass::stop()" << endl;
		this->var = 0;
	}

	friend ostream& operator<<(ostream& os, SonClass);

	string getid() { return id; }
};

ostream& operator<<(ostream& os, SonClass tmp)
{
	os << boost::format("id: %1$-8svar: %2$-8d\n") % tmp.id % tmp.var;
	return os;
}


void test_bind_class_func()
{
	SonClass s("hello");
	cout << s << endl;
	auto ptr_func = std::bind(&SonClass::stop, &s);
	ptr_func();
	cout << s << endl;
}



typedef void (*p)(int data);
typedef void (MyClass::* call_back)();
map<string, MyClass*> map_id_var;

static bool del(const string& id)
{
	auto it = map_id_var.find(id);
	if (it != map_id_var.end()) {
		it->second->stop();
		return true;
	}
	return false;
}

struct A {
	string name;
	int a;

	A(string _name, int _a) :name(_name), a(_a) {};
};

void test_circular_buffer()
{
	boost::circular_buffer<int> c(3);
	c.push_back(1);
	c.push_back(2);
	c.push_back(3);
	cout << c[0] << ' ' << c[1] << ' ' << c[2] << endl;
	c.push_back(4);
	c.push_back(5);
	cout << c[0] << ' ' << c[1] << ' ' << c[2] << endl;
}



int main()
{
	test_bind_class_func();
}


